#include "cv.h"
#include "cascadeclassifier.h"

using namespace std;

int main( int argc, char* argv[] ) {
	CvCascadeClassifier classifier;
	String cascadeDirName, vecName, bgName;
	int numPos    = 2000;
	int numNeg    = 1000;
	int numStages = 20;
	int precalcValBufSize = 256,
		precalcIdxBufSize = 256;
	bool baseFormatSave = false;

	CvCascadeParams cascadeParams;
	CvCascadeBoostParams stageParams;
	Ptr<CvFeatureParams> featureParams[] = { Ptr<CvFeatureParams>(new CvHaarFeatureParams),
										   Ptr<CvFeatureParams>(new CvLBPFeatureParams)
										   };
	int fc = sizeof(featureParams) / sizeof(featureParams[0]);
	if ( argc == 1 ) {
		cout << "Usage: " << argv[0] << endl;
		cout << "  -data <cascade_dir_name>" << endl;
		cout << "  -vec <vec_file_name>" << endl;
		cout << "  -bg <background_file_name>" << endl;
		cout << "  [-numPos <number_of_positive_samples = " << numPos << ">]" << endl;
		cout << "  [-numNeg <number_of_negative_samples = " << numNeg << ">]" << endl;
		cout << "  [-numStages <number_of_stages = " << numStages << ">]" << endl;
		cout << "  [-precalcValBufSize <precalculated_vals_buffer_size_in_Mb = " << precalcValBufSize << ">]" << endl;
		cout << "  [-precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb = " << precalcIdxBufSize << ">]" << endl;
		cout << "  [-baseFormatSave]" << endl;
		cascadeParams.printDefaults();
		stageParams.printDefaults();
		for ( int fi = 0; fi < fc; fi++ ) {
			featureParams[fi]->printDefaults();
		}
		return 0;
	}

	for ( int i = 1; i < argc; i++ ) {
		bool set = false;
		if ( !strcmp( argv[i], "-data" ) ) {
			cascadeDirName = argv[++i];
		} else if ( !strcmp( argv[i], "-vec" ) ) {
			vecName = argv[++i];
		} else if ( !strcmp( argv[i], "-bg" ) ) {
			bgName = argv[++i];
		} else if ( !strcmp( argv[i], "-numPos" ) ) {
			numPos = atoi( argv[++i] );
		} else if ( !strcmp( argv[i], "-numNeg" ) ) {
			numNeg = atoi( argv[++i] );
		} else if ( !strcmp( argv[i], "-numStages" ) ) {
			numStages = atoi( argv[++i] );
		} else if ( !strcmp( argv[i], "-precalcValBufSize" ) ) {
			precalcValBufSize = atoi( argv[++i] );
		} else if ( !strcmp( argv[i], "-precalcIdxBufSize" ) ) {
			precalcIdxBufSize = atoi( argv[++i] );
		} else if ( !strcmp( argv[i], "-baseFormatSave" ) ) {
			baseFormatSave = true;
		} else if ( cascadeParams.scanAttr( argv[i], argv[i+1] ) ) { i++; }
		else if ( stageParams.scanAttr( argv[i], argv[i+1] ) ) { i++; }
		else if ( !set ) {
			for ( int fi = 0; fi < fc; fi++ ) {
				set = featureParams[fi]->scanAttr(argv[i], argv[i+1]);
				if ( !set ) {
					i++;
					break;
				}
			}
		}
	}

	classifier.train( cascadeDirName,
					  vecName,
					  bgName,
					  numPos, numNeg,
					  precalcValBufSize, precalcIdxBufSize,
					  numStages,
					  cascadeParams,
					  *featureParams[cascadeParams.featureType],
					  stageParams,
					  baseFormatSave );
	return 0;
}
